package com.xiongtian.springframework.aop.aspectj;

import com.xiongtian.springframework.aop.ClassFilter;
import com.xiongtian.springframework.aop.MethodMatcher;
import com.xiongtian.springframework.aop.Pointcut;
import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.PointcutPrimitive;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * @Author: xiongtian
 * @CreateTime: 2025-04-17  11:40
 * @Version: 1.0
 * @Description: 方法匹配器
 * <p>
 * Core Spring pointcut abstraction.
 * </p>
 */

public class AspectJExpressionPointcut implements Pointcut, ClassFilter, MethodMatcher {

    /**
     * 支持的切点表达式类型
     * <p>
     * 1. execution
     */
    private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<>();

    /**
     * 初始化支持的切点表达式类型
     */
    static {
        SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
    }

    /**
     * 切点表达式
     * <p>
     * 1. 用于解析切点表达式
     * 2. 用于判断方法是否匹配切点表达式
     */
    private final PointcutExpression pointcutExpression;

    /**
     * 构造函数
     *
     * @param expression 切点表达式
     */
    public AspectJExpressionPointcut(String expression) {
        PointcutParser pointcutParser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(SUPPORTED_PRIMITIVES, this.getClass().getClassLoader());
        pointcutExpression = pointcutParser.parsePointcutExpression(expression);
    }

    /**
     * 判断类是否匹配切点表达式
     *
     * @param clazz 类
     * @return 是否匹配
     */
    @Override
    public boolean matches(Class<?> clazz) {
        return pointcutExpression.couldMatchJoinPointsInType(clazz);
    }

    /**
     * 判断方法是否匹配切点表达式
     *
     * @param method      方法
     * @param targetClass 目标类
     * @return 是否匹配
     */
    @Override
    public boolean matches(Method method, Class<?> targetClass) {
        return pointcutExpression.matchesMethodExecution(method).alwaysMatches();
    }

    /**
     * 获取类过滤器
     *
     * @return 类过滤器
     */
    @Override
    public ClassFilter getClassFilter() {
        return this;
    }

    /**
     * 获取方法匹配器
     *
     * @return 方法匹配器
     */
    @Override
    public MethodMatcher getMethodMatcher() {
        return this;
    }
}
